#ifndef TASK_H
#define TASK_H 

#include "Table.h"
#include "List.h"
#include "utility/Types.h"
#include "Sem.h"

typedef struct Task
{
    enum {
        CREATED,
        READY,
        RUNNING,
        WAITING,
        SLEEPING
    } state;

    char taskName[32];
    TssDescType tss;

    int processId;
    struct Task* parent;
    // GDT index * 8
    uint16_t tssSelector;
    ListNodeType readyNode;
    ListNodeType allNode;
    ListNodeType waitNode;

    int ticks;
    int remainTicks;
    int sleepTicks;
} TaskType;

typedef struct TaskArgs
{
    uint32_t retAddr;
    uint32_t argc;
    char** argv;
} TaskArgsType;


uint32_t InitTask(TaskType* task, const char* name, uint32_t eip, uint32_t esp, bool isKernelTask);
void InitFirstTask(void);
void SwitchTask(TaskType* from, TaskType* to);

typedef struct TaskManager
{
    TaskType* currentTask;
    TaskType firstTask;
    TaskType idleTask;
    ListType taskList;
    ListType readyTaskList;
    ListType sleepTaskList;
    int appCodeSelector;
    int appDataSelector;
} TaskManagerType;

void InitTaskManager();
TaskType* GetFirstTask();
TaskType* GetCurrentTask();

void SetTaskReady(TaskType* task);
void SetTaskBlock(TaskType* task);
void SetTaskSleep(TaskType* task, uint32_t ticks);
void SetTaskWakeUp(TaskType* task);
void SetTaskWait(TaskType* task, SemaphoreType* sem);
void DispatchTask(void);
void TaskTimeTick(void);
void StartTask(TaskType* task);

void SysYield(void);
void SysSleep(uint32_t ms);
int SysGetPid(void);
int SysFork(void);
int SysExecve(char* name, char* argv[], char* env[]);

#endif